package util;

import java.util.HashSet;

public class GeoEdge
{
	public GeoVertex start;
	public GeoVertex end;
	public GeoVertex extension;
	
	protected double length;

	public GeoEdge()
	{
		start = null;
		end = null;
		extension = null;
		length = 0.0;
	}
	
	public GeoEdge(GeoVertex s, GeoVertex e)
	{
		init(s, e);
		extension = null;
	}
	
	public GeoEdge(GeoVertex s, GeoVertex p, GeoVertex e)
	{
		init(s, p);
		extension = e; // this edge is thus a parametic edge where (s,e) is the full edge and (s,p) is part of the edge
	}
	
	private void init(GeoVertex s, GeoVertex e)
	{
		start = s;
		end = e;
		length = s.distance3D(e);
	}
	
	public double length() { return length; }
	public boolean isParametric() { return extension != null; }
	
	// assume 0.0 <= t <= 1.0
	public GeoVertex parametricGeoVertex(double t)
	{
		double mid_x = start.x() + t*(end.x()-start.x());
		double mid_y = start.y() + t*(end.y()-start.y());
		double mid_z = start.z() + t*(end.z()-start.z());
		
		GeoVertex mid = new GeoVertex(mid_x, mid_y, mid_z);
		
		// run through the triangles of start and end to see which ones are shared
		HashSet<Integer> startTriangles = start.trianglekeys;
		HashSet<Integer> endTriangles = end.trianglekeys;
		
		for (Integer tk: startTriangles)
			if (endTriangles.contains(tk))
				mid.trianglekeys.add(tk);
		
		// start and end are the only neighbours of this new vertex
		mid.neighbourkeys.add(start.id);
		mid.neighbourkeys.add(end.id);
		
		double d1 = length*t;
		double d2 = length*(1.0 - t);
		double denom = d1 + d2;
		mid.curvatureAnisotropic = (d2/denom)*start.curvatureAnisotropic + (d1/denom)*end.curvatureAnisotropic;
		mid.curvatureAnisotropicAveraged= (d2/denom)*start.curvatureAnisotropicAveraged + (d1/denom)*end.curvatureAnisotropicAveraged;
		return mid;
	}
	
	// return the direction of this edge
	public double[] getDirectionVector()
	{
		double[] dir = new double[3];
		dir[0] = end.x() - start.x();
		dir[1] = end.y() - start.y();
		dir[2] = end.z() - start.z();
		return dir;
	}
	
	// return the direction of this edge
	public double[] getDirectionVector_Normalized()
	{
		double[] dir = new double[3];
		dir[0] = (end.x() - start.x())/length;
		dir[1] = (end.y() - start.y())/length;
		dir[2] = (end.z() - start.z())/length;
		return dir;
	}
	
	public boolean equals(Object o)
	{
		GeoEdge e = (GeoEdge)o;
		return (e.start.equals(this.start) && e.end.equals(this.end)) || (e.end.equals(this.start) && e.start.equals(this.end));
	}
}
